package com.kdtech.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.jsoup.select.Elements;


public class StringUtils extends org.apache.commons.lang.StringUtils {

	/** The ng. */
	private static SecureRandom ng = new SecureRandom();

	/**
	 * 取得>=0 <max的随机整数
	 *
	 * @param max
	 *            the max
	 *
	 * @return the int random
	 */
	public static int getIntRandom(int max) {

		// 效率：Random.nextInt > Math.random()*max > SecureRandom.nextInt
		// SecureRandom增强型随机数
		return ng.nextInt(max);

		// return (int)(Math.random()*max);
	}

	private static final String regEx_html = "<[^>]+>"; // 定义HTML标签的正则表达式
	public static String delHtmlTag(String htmlStr){
		if(htmlStr!=null){
		 Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
	        Matcher m_html = p_html.matcher(htmlStr);
	        htmlStr = m_html.replaceAll(""); // 过滤html标签
		}
		return htmlStr;
	}
	/**
	 * Gets the long random.
	 *
	 * @return the long random
	 */
	public static long getLongRandom() {
		return ng.nextLong();
	}

	/**
	 * Generate seed.
	 *
	 * @return the byte[]
	 */
	public static byte[] generateSeed() {
		return ng.generateSeed(ng.nextInt(1024));
	}

	/**
	 * Generate seed.
	 *
	 * @param numBytes
	 *            the num bytes
	 *
	 * @return the byte[]
	 */
	public static byte[] generateSeed(int numBytes) {
		return ng.generateSeed(numBytes);
	}

	/**
	 * Gets the uUID.
	 *
	 * @return the uUID
	 */
	public static String getUUID() {
		UUID u = UUID.randomUUID();
		return u.toString().replaceAll("-", "");
	}

	/**
	 * Gets the random hex string.
	 *
	 * @param length
	 *            the length
	 *
	 * @return the random hex string
	 */
	public static String getRandomHexString(int length) {
		byte[] randomBytes = new byte[length];
		ng.nextBytes(randomBytes);
		return encodeHex(randomBytes);
	}

	/**
	 * Encode hex.
	 *
	 * @param bytes
	 *            the bytes
	 *
	 * @return the string
	 */
	public static String encodeHex(byte[] bytes) {
		if (bytes == null || bytes.length == 0) {
			return null;
		}
		StringBuilder buf = new StringBuilder(bytes.length * 2);
		int i;

		for (i = 0; i < bytes.length; i++) {
			if (((int) bytes[i] & 0xff) < 0x10) {
				buf.append("0");
			}
			buf.append(Long.toString((int) bytes[i] & 0xff, 16));
		}
		return buf.toString();
	}

	/**
	 * Decode hex.
	 *
	 * @param hex
	 *            the hex
	 *
	 * @return the byte[]
	 */
	public static final byte[] decodeHex(String hex) {
		char[] chars = hex.toCharArray();
		byte[] bytes = new byte[chars.length / 2];
		int byteCount = 0;
		for (int i = 0; i < chars.length; i += 2) {
			byte newByte = 0x00;
			newByte |= hexCharToByte(chars[i]);
			newByte <<= 4;
			newByte |= hexCharToByte(chars[i + 1]);
			bytes[byteCount] = newByte;
			byteCount++;
		}
		return bytes;
	}

	/**
	 * Hex char to byte.
	 *
	 * @param ch
	 *            the ch
	 *
	 * @return the byte
	 */
	private static final byte hexCharToByte(char ch) {
		switch (ch) {
		case '0':
			return 0x00;
		case '1':
			return 0x01;
		case '2':
			return 0x02;
		case '3':
			return 0x03;
		case '4':
			return 0x04;
		case '5':
			return 0x05;
		case '6':
			return 0x06;
		case '7':
			return 0x07;
		case '8':
			return 0x08;
		case '9':
			return 0x09;
		case 'a':
			return 0x0A;
		case 'b':
			return 0x0B;
		case 'c':
			return 0x0C;
		case 'd':
			return 0x0D;
		case 'e':
			return 0x0E;
		case 'f':
			return 0x0F;
		case 'A':
			return 0x0A;
		case 'B':
			return 0x0B;
		case 'C':
			return 0x0C;
		case 'D':
			return 0x0D;
		case 'E':
			return 0x0E;
		case 'F':
			return 0x0F;
		}
		return 0x00;
	}

	/**
	 * Md5.
	 *
	 * @param data
	 *            the data
	 *
	 * @return the string
	 */
	public static final byte[] md5(String data) {
		MessageDigest md5 = null;
		try {
			md5 = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			System.err.println("Failed to load the MD5 MessageDigest.");
		}
		try {
			md5.update(data.getBytes("GBK"));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return md5.digest();
	}

	public static final String md5String(String data) {
		return encodeHex(md5(data));
	}

	/**
	 * 获得length长度的随机字�?字符范围�?2-126 �? '�?~'.
	 *
	 * @param length
	 *            the length
	 *
	 * @return the random string
	 */
	public static String getRandomString(int length) {
		StringBuilder sb = new StringBuilder(length);
		for (int j = 0; j < length; j++) {
			sb.append((char) (getIntRandom(95) + 32));
		}
		return sb.toString();
	}

	/**
	 * Gets the random number string.
	 *
	 * @param length
	 *            the length
	 *
	 * @return the random number string
	 */
	public static String getRandomNumberString(int length) {
		StringBuilder sb = new StringBuilder(length);
		for (int j = 0; j < length; j++) {
			sb.append(getIntRandom(10));
		}
		return sb.toString();
	}

	/**
	 * 判断Class是否经过OpenJPA enhancher处理.
	 *
	 * @param c
	 *            the c
	 *
	 * @return true, if checks if is open jpa enhanced class
	 */
	public static boolean isOpenJPAEnhancedClass(Class<?> c) {
		return contains(c.toString(),
				"org.apache.openjpa.enhance.com$win2g$g2s$domain$po$");
	}

	public static String leftZeroPad(int num, int size) {
		return leftZeroPad(String.valueOf(num), size);
	}

	public static String leftZeroPad(long num, int size) {
		return leftZeroPad(String.valueOf(num), size);
	}

	public static String leftZeroPad(String num, int size) {
		return leftPad(num, size, '0');
	}

	public static String getFname(int num, String merchId) {
		Date sysdate = new Date();
		return merchId + "." + DateUtils.format(sysdate) + "."
				+ StringUtils.leftZeroPad(num, 2);
	}

	public static boolean isNullOrEmpty(String property) {
		return isBlank(property);
	}

	public static String right(String str, int length) {
		if (isNullOrEmpty(str) || str.length() <= length)
			return str;
		return substring(str, str.length() - 5, str.length());
	}

	public static int indexOfIgnoreCase(String sqlHeader, String find) {
		return sqlHeader.toLowerCase().indexOf(find.toLowerCase());
	}

	public static String removeUnnecessaryChar(String str) {
		String regex = "[\r\n]";
		return str.replaceAll(regex, "");
	}

	public static String trimAllWhitespace(String str) {
		if (!isNullOrEmpty(str)) {
			return str;
		}
		StringBuilder sb = new StringBuilder(str);
		int index = 0;
		while (sb.length() > index) {
			if (Character.isWhitespace(sb.charAt(index))) {
				sb.deleteCharAt(index);
			} else {
				index++;
			}
		}
		return sb.toString();
	}

	public static String splitString(String str, int len, String elide) {

		if (str == null) {

			return "";

		}

		byte[] strByte = str.getBytes();

		int strLen = strByte.length;

		int elideLen = (elide.trim().length() == 0) ? 0
				: elide.getBytes().length;

		if (len >= strLen || len < 1) {

			return str;

		}

		if (len - elideLen > 0) {

			len = len - elideLen;

		}

		int count = 0;

		for (int i = 0; i < len; i++) {

			int value = (int) strByte[i];

			if (value < 0) {

				count++;

			}

		}

		if (count % 2 != 0) {

			len = (len == 1) ? len + 1 : len - 1;

		}

		return new String(strByte, 0, len) + elide.trim();

	}

	public static String getString(byte[] b) {
		if (b != null) {
			return new String(b);
		}
		return "";
	}

	public static String parseNull(String str) {
		if ("null".equalsIgnoreCase(str)) {
			return null;
		}
		return str;
	}

	

	/**
	 * 从字节数组获取对象
	 */
	private static Object bytes2Object(byte[] objBytes) throws Exception {
		if (objBytes == null || objBytes.length == 0) {
			return null;
		}
		ByteArrayInputStream bi = new ByteArrayInputStream(objBytes);
		ObjectInputStream oi = new ObjectInputStream(bi);
		return oi.readObject();
	}

	/**
	 * 从对象获取一个字节数组
	 */
	private static byte[] object2Bytes(Object obj) throws Exception {
		if (obj == null) {
			return null;
		}
		ByteArrayOutputStream bo = new ByteArrayOutputStream();
		ObjectOutputStream oo = new ObjectOutputStream(bo);
		oo.writeObject(obj);
		return bo.toByteArray();
	}

	

	public static String getListString(List<String> linkUrl2) {
		if (linkUrl2 == null) {
			return "";
		}
		StringBuilder sb = new StringBuilder();
		for (String string : linkUrl2) {
			string = string.replace("\t", "");
			sb.append(string).append("\t");
		}
		return sb.toString();
	}

	public static List<String> getStringList(String str) {
		List<String> list = new ArrayList<String>();
		String[] strs = str.split("\t");
		for (String string : strs) {
			list.add(string);
		}
		return list;
	}

	/**
	 * 判断两个对象是否相等
	 * */
	public static boolean equals(Object object, Object another)
			throws Exception {
		if (!object.getClass().equals(another.getClass()))
			return false;
		boolean result = true;
		Class<?> _class = object.getClass();
		Field[] fields = _class.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			fields[i].setAccessible(true);// 访问private protect修饰
			Object value = fields[i].get(object);
			Object another_value = fields[i].get(another);
			if (value != another_value) {
				return false;
			}
		}
		return result;
	}

	public static String trimQuanJiaoSpace(String input) {
		if (input == null)
			return null;
		try {
			return input.replaceAll("　", " ").trim();
		} catch (Exception e) {
			return "";
		}
	}

	public static String getMD5(String message) {
		int hashCode = message.hashCode();
		return String.valueOf(hashCode);
	}

	/**
	 * 转换时长的格式 01:15:36 转换成分钟
	 * */
	public static long getDuration(String duration) {
		if (isBlank(duration))
			return 0;
		if(duration.indexOf("分钟")!=-1){
			duration = duration.replace("分钟", "");
			try {
				int iDuration = Integer.parseInt(duration);
				return iDuration;
			} catch (NumberFormatException e) {
				// TODO Auto-generated catch block
			}
		}
		duration = duration.replaceAll("：", ":");
		String[] split = duration.split(":");
		long _duration = 0;
		try {
			int length = split.length;
			if (length == 3) {
				_duration = Integer.parseInt(split[0]) * 60
						+ Integer.parseInt(split[1]);
			} else if (length == 2) {
				_duration = Integer.parseInt(split[0]);
				if (_duration == 0) {
					_duration += 1;
				}
			} else if (length == 1) {
				_duration += 1;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return _duration;
	}
	public static int indexOf(String string,char subString,int num){
		int _num = 0;
		char[] charArray = string.toCharArray();
		for (int i = 0; i < charArray.length; i++) {
			if(subString==charArray[i]){
				_num++;
				if(_num==num)
					return i;
			}
		}
		return -1;
	}

	public static String trimSpace(String str) {
		if(isNotEmpty(str)){
			return str.trim();
		}
		return str;
	}

	public static String delAllSpace(String str){
		if(isNotEmpty(str)){
			   str = str.replaceAll("\\s*|\t|\r|\n|", "").replace("　", "").replace(" ", "");
		}
		return str;
	}

	public static boolean startsWithAny(String url, String... prefixs) {
		for (String prefix : prefixs) {
			if(url.startsWith(prefix)){
				return true;
			}
		}
		return false;
	}

	public static int getCharCount(String url,char c) {
        int count = 0;
        for( int i=0; i < url.length(); i++ ) {
          if(url.charAt(i) == c )
            count++;
        }

        return count;
      }

	public static boolean containsAny(String str, String... searchStr) {
		for (String string : searchStr) {
			if(contains(str, string)){
				return true;
			}
		}
		return false;
	}

	public static boolean equalsAny(String url, String...strings) {
		for (String string : strings) {
			if(equals(url, string)){
				return true;
			}
		}
		return false;
	}

	public static boolean equalsIgnoreCaseAny(String url, String...strings) {
		if (strings==null){
			return false;
		}
		for (String string : strings) {
			if(equalsIgnoreCase(url, string)){
				return true;
			}
		}
		return false;
	}

	public static boolean isNotEmptyAll(String ...strings ) {
		for (String string : strings) {
			if (isNullOrEmpty(string)){
				return false;
			}
		}
		return true;
	}

	/**
	 * 将中文转为unicode码
	 *
	 * @param gbString
	 * @return
	 */
	public static String encodeUnicode(final String gbString) {
		char[] utfBytes = gbString.toCharArray();
		String unicodeBytes = "";
		for (int byteIndex = 0; byteIndex < utfBytes.length; byteIndex++) {
			String hexB = Integer.toHexString(utfBytes[byteIndex]);
			if (hexB.length() <= 2) {
				hexB = "00" + hexB;
			}
			unicodeBytes = unicodeBytes + "\\\\u" + hexB;
		}
		return unicodeBytes;
	}

	/*****************************************************
	 * 功能介绍:将unicode字符串转为汉字 输入参数:源unicode字符串 输出参数:转换后的字符串
	 * @param dataStr 需要解码的字符串
	 * @param isHoldWord 是否保存非 Unicode 编码的字符串
	 *****************************************************/

	public static String decodeUnicode(final String dataStr	){
		return decodeUnicode(dataStr,true);
	}

	public static String decodeUnicode(final String dataStr, boolean isHoldWord	){
		final String unicodeRegex = "\\\\u[a-f0-9]{4}";
		StringBuffer buffer = new StringBuffer();
		Matcher matcher = Pattern.compile(unicodeRegex, Pattern.CASE_INSENSITIVE).matcher(dataStr);
		int unicodeStart = 0;
		int unicodeEnd = 0;
		int wordStart = 0;
		while(matcher.find()){
			String charStr = matcher.group().substring(2);
			unicodeStart = matcher.start();
			unicodeEnd = matcher.end();

			if(isHoldWord){
				if(unicodeStart > wordStart){
					buffer.append(dataStr.substring(wordStart, unicodeStart));
				}
			}

			char letter;
			try {
				letter = (char) Integer.parseInt(charStr, 16);
				buffer.append(new Character(letter).toString());
			} catch (NumberFormatException e) {

				// e.printStackTrace();
			}

			wordStart = unicodeEnd;
		}

		if(isHoldWord && unicodeEnd < dataStr.length()){
			buffer.append(dataStr.substring(unicodeEnd));
		}

		return buffer.toString();
	}

	public static boolean isNumeric(char chr) {
		if (chr>='0' && chr<='9'){
			return true;
		}
		return false;
	}

	public static String urlEncodeUTF8(String str) {
		try {
			return URLEncoder.encode(str, "UTF8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}

	public static String urlDecodeUTF8(String str) {
		try {
			return URLDecoder.decode(str, "UTF8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}

	public static boolean containsAll(String title, String[] split) {
		if (title!=null && split!=null){
			for (String string : split) {
				if (title.indexOf(string)==-1){
					return false;
				}
			}
		}else{
			return false;
		}

		return true;
	}

	public static String substringBefore(String string, String separator,	int charCount) {
		int indexOf = 0;
		for (int i = 0; i < charCount; i++) {

			indexOf = string.indexOf(separator,indexOf+1);
		}
		if (indexOf>=0 ){
			return string.substring(0, indexOf);
		}
		return null;
	}



	public static String trimLeft(String text) {
		StringBuilder sb = new StringBuilder(text);
		int index = 0;

		//trim left
		while (sb.length() > index) {
			if (Character.isWhitespace(sb.charAt(index))) {
				sb.deleteCharAt(index);
			} else {
				break;
			}
		}
		return sb.toString();
	}

	public static String trimLeftRightWhiteSpace(String text) {
		StringBuilder sb = new StringBuilder(text);
		int index = 0;

		//trim left
		while (sb.length() > index) {
			if (Character.isWhitespace(sb.charAt(index))) {
				sb.deleteCharAt(index);
			} else {
				break;
			}
		}

		//trim right
		while (sb.length() > 0) {
			if (Character.isWhitespace(sb.charAt(sb.length()-1))) {
				sb.deleteCharAt(sb.length()-1);
			} else {
				break;
			}
		}
		return sb.toString();
	}

	public static String substringBeforeWhiteSpace(String text) {
		StringBuilder sb = new StringBuilder(text);
		int index = 0;
		//trim left
		while (sb.length() > index) {
			char charAt = sb.charAt(index);
//			System.out.println("(int)charAt->" + (int)charAt);
//			System.out.println("Character.isSpaceChar(ch)" +Character.isSpaceChar(charAt));
//			System.out.println("Character.isWhitespace(charAt)->" + (int)charAt+Character.isWhitespace(charAt) );
			if (Character.isWhitespace(charAt) || Character.isSpaceChar(charAt)) {
				sb.delete(index, sb.length());
			} else {
				index++;
			}
		}
		return sb.toString();
	}




	public static String replaceAllToSpace(String text, String... replaceStrs) {
		if (text==null) return null;
		for (String string : replaceStrs) {
			text = text.replace(string, " ");
			if (text==null)return null;
		}
		return text;
	}

	/**
	 * 半角转全角
	 *
	 * @param input
	 * @return 全角字符串.
	 */
	public static String ToSBC(String input) {
		char c[] = input.toCharArray();
		for (int i = 0; i < c.length; i++) {
			if (c[i] == ' ') {
				c[i] = '\u3000';
			} else if (c[i] < '\177') {
				c[i] = (char) (c[i] + 65248);

			}
		}
		return new String(c);
	}

	/**
	 * 全角转半角
	 *
	 * @param input
	 * @return 半角字符串
	 */
	public static String ToDBC(String input) {
		char c[] = input.toCharArray();
		for (int i = 0; i < c.length; i++) {
			if (c[i] == '\u3000') {
				c[i] = ' ';
			} else if (c[i] > '\uFF00' && c[i] < '\uFF5F') {
				c[i] = (char) (c[i] - 65248);
			}
		}
		String returnString = new String(c);
		return returnString;
	}

	public static boolean containsAnyIgnoreCase(String text, String ...strings ) {
		if (text==null || strings==null){
			return false;
		}

		for (String string : strings) {
			if(containsIgnoreCase(text, string)){
				return true;
			}
		}
		return false;
	}

	public static boolean endsWithAnyIgnoreCase(String str, String... suffix) {
		if (str==null || suffix==null){
			return false;
		}
		for (String string : suffix) {
			if(endsWithIgnoreCase(str, string)){
				return true;
			}
		}
		return false;
	}

	public static String getNumRegex(String str){
		int numCounts=0;
		String ret="";
		boolean isMatchNum=false;
		for(int i=0;i<str.length();i++){
			String sub=str.substring(i, i+1);
			if(sub.matches("[0-9]+")){
				isMatchNum=true;
				numCounts++;
			}else{
				if(isMatchNum){
					ret+="[0-9]{"+numCounts+"}";
				}
				isMatchNum=false;
				numCounts=0;
			}
			if(numCounts==0){
				ret+=sub;
			}
		}
		return ret;
	}

	
	public static boolean isBlank(Elements content) {
		return content == null || isBlank(content.text());
	}

}
